<?php

namespace app\api\controller;

use app\common\controller\Api;
use think\Config;
use GuzzleHttp\Client;
use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver as GdDriver;
use Intervention\Image\Geometry\Line;
use Intervention\Image\Colors\Rgb\Color;
use Intervention\Image\Geometry\Point; // 新增引入 Point 类
use think\Validate;
use app\common\model\HomeworkCorrections;
use app\common\model\TalkRecord;
use app\common\model\TimuRecord;
use app\common\model\Zhishi;
use app\common\model\TimuTalk;
use app\common\model\TimuQuestions;
use app\common\model\DiagnosticReport;
use app\common\model\TimuZhishiRecord;
use app\common\model\Essay;
use app\common\model\ArticalRecord;
use app\common\model\Homework;
use app\common\model\DayiRecord;
use think\Db;

/**
 * ai接口
 */
class Ai extends Api
{
    protected $noNeedLogin = ['checkHomework','uploadHomework','homeworkToAiWork','homeworkToAnnotateImage','aiTalk','aiQuestion','aiArticalCheck'];
    protected $noNeedRight = '*';
    public function _initialize()
    {
        parent::_initialize();

        if (!Config::get('fastadmin.usercenter')) {
            $this->error(__('User center already closed'));
        }

    }
    /**
     * ai互动
     * @ApiMethod (POST)
     * @ApiParams (name="user_id", type="int", required=true, description="学生id")
     * @ApiParams (name="content", type="text", required=true, description="对话内容")
     */
    public function aiTalk(){
        $userId = $this->request->post('user_id');
        $content = $this->request->post('content','');
        if (!$userId){
            $this->error('参数错误');
        }
        if (!$content){
            $this->error('请输入对话内容');
        }
        $response = $this->callDeepSeekAPIToText($content,$userId);
        $this->success('操作成功',$response);

    }
    
    /**
     * ai错题对话
     * @ApiMethod (POST)
     * @ApiParams (name="user_id", type="int", required=true, description="学生id")
     * @ApiParams (name="content", type="text", required=true, description="对话内容")
     * @ApiParams (name="timu_id", type="text", required=true, description="题目ID")
     * @ApiParams (name="type", type="text", required=true, description="类型")  // 1:对话 2:提问
     */
    public function aiIssue(){
        $userId = $this->request->post('user_id');
        $content = $this->request->post('content','');
        $timuId = $this->request->post('timu_id');
        $type = $this->request->post('type');
        if (!$userId){
            $this->error('参数错误');
        }
        if (!$content){
            $this->error('请输入对话内容');
        }
        if (!$type){
            $this->error('请输入对话内容');
        }
        if($type == 2){
            $content = '根据知识点' . $content . '生成三个相关题目的疑问。数组格式返回,例如 ["题目1","题目2"]';
        }
        $response = $this->callDeepSeekAPIAiIssue($content,$userId,$timuId,$type);
        $this->success('操作成功',$response);
    }
    
    public function callDeepSeekAPIAiIssue($content,$userId,$timuId,$type)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }
        try {

            $apiEndpoint =  'chat/completions';
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
                "model" => "doubao-1-5-thinking-vision-pro-250428",
                // "model" => "deepseek-v3-250324",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        "content" => $content
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseTextApiAiIssue($apiResponse,$content,$userId,$timuId,$type);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }
    
    private function parseTextApiAiIssue($apiResponse, $content,$userId,$timuId,$type)
    {

        $result = $apiResponse['choices'][0]['message']['content'];
        $arr = [
            'answer'=>$result
        ];
        if($type == 2){
            TimuQuestions::create([
                'user_id' => $userId,
                'content' => $content,
                'answer' => $result,
                'timu_id' => $timuId,
            ]);
        }else{
            TimuTalk::create([
                'user_id' => $userId,
                'content' => $content,
                'answer' => $result,
                'timu_id' => $timuId,
            ]);
        }
        //记录到表中wdl_talk_record
        // TalkRecord::create([
        //     'user_id' => $userId,
        //     'content' => $content,
        //     'answer' => $result,
        // ]);
        return $arr;
    }

    /**
     * 批改作文
     * @ApiMethod (POST)
     * @ApiParams (name="student_id", type="int", required=true, description="学生id")
     * @ApiParams (name="file", type="file", required=true, description="上传的文件")
     */
    public function  aiArticalCheck()
    {
        // 1. 验证并获取上传的图片
        $param = input();
        $files = $param['files'];
        $studentId = $this->request->post('student_id');

        if (!$files) {
            $this->error('请上传作文的图片');
        }

        if (!$studentId){
            $this->error('参数错误');
        }

        // 当前时间
        $now = time();
        // 当天起始时间戳（00:00:00）
        $todayStart = strtotime(date('Y-m-d 00:00:00', $now));

        // 查询今天最大的 orderNo
        $maxOrderNo = Db::name('artical_record')
            ->where('create_time', '>=', $todayStart)
            ->max('orderNo');
        if ($maxOrderNo == null) {
            $maxOrderNo = 1; // 如果没有记录，默认为1
        }
        $content = '';
        $result = '';
        $subject = '';
        $allfullUrl = '';
        $blips = '';
        $advice = '';
        foreach ($files as $fullUrl) {
            //对图片进行deepseek处理
            $response = $this->aiArtical($fullUrl);
            $resource = $response['resource'];
            
            // if (!isset($resource['content'], $resource['answer'], $resource['subject'])) {
            //     throw new \Exception("AI返回数据格式错误：" . json_encode($resource));
            // }
            $content .= $resource['content'] ?? '';
            $result .= $resource['answer'] ?? '';
            $subject = $resource['subject'] ?? '';
            $blips = $resource['blips'] ?? '';
            $advice = $resource['advice'] ?? '';
            $allfullUrl = $allfullUrl.','.$fullUrl;

        }
        $datiRecord = [
            'student_id' => $studentId,
            'image' => $allfullUrl,
            'orderNo' => $maxOrderNo + 1,
            'content' => $content,
            'answer' => $result,
            'advice' => $advice,
            'subject' => $subject,
            'blips' => $blips,
        ];
        ArticalRecord::create($datiRecord);
        //将多张图片进行一次性请求ai
        $this->success('作文解析成功',['content'=>$content,'result'=>$result,'blips'=>$blips,'advice'=>$advice]);
    }

    /**
     * 搜题答疑
     * @ApiMethod (POST)
     * @ApiParams (name="user_id", type="int", required=true, description="学生id")
     * @ApiParams (name="file", type="file", required=true, description="上传的文件")
     */
    public function  aiQuestion()
    {
            // 1. 验证并获取上传的图片
            $param = input();
            $files = $param['files'];
            $fullUrl = $files[0];
            $studentId = $param['student_id'];

            if (!$fullUrl) {
                $this->error('请上传答疑的图片');
            }
            if (!$studentId){
                $this->error('参数错误');
            }

            //对图片进行deepseek处理
            $response = $this->aiDayi($fullUrl);
            $resource = json_decode($response['resource'] ?? '', true) ?: [];
            if (!isset($resource['answer'], $resource['question'], $resource['subject'])) {
                throw new \Exception("AI返回数据格式错误：" . json_encode($resource));
            }
            $datiRecord = [
                'student_id' => $studentId,
                'image' => $fullUrl,
                'answer' => $resource['answer'],
                'question' => $resource['question'],
                'subject' => $resource['subject'],
            ];
            DayiRecord::create($datiRecord);
            $this->success('作业解析成功',['result'=>$datiRecord]);

    }
    /**
     * 提交作业(图片)
     *
     * @ApiMethod (POST)
     * @ApiParams (name="student_id", type="int", required=true, description="学生id")
     * @ApiParams (name="file", type="file", required=true, description="上传的文件")
     * @ApiParams (name="assignment_id", type="int", required=true, description="作业任务id")
     * @ApiParams (name="type", type="int", required=true, description="1提交作业 2提交作文 3搜题答疑")
     */
    public function uploadHomework()
    {
        // 1. 验证并获取上传的图片
        $file = $this->request->file('file');
        $studentId = $this->request->post('student_id');
        $assignmentId = $this->request->post('assignment_id');
        $type = $this->request->post('type',1);

        if (!$file) {
            $this->error('请上传图片');
        }

        if (!$studentId){
            $this->error('参数错误');
        }

        $info = $file->getInfo();
        $extension = $this->getExtensionFromMimeType($info['type']);
        // 验证文件大小和类型
        $arr_ext = ["jpg","jpeg","png","gif"];
        if (!in_array($extension, $arr_ext)){
            $this->error('图片格式不支持');
        }

        $timestamp = time(); // 当前时间戳
        $currentDate = date('YmdHis', $timestamp);

        $randomNumber = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
        $fileName = $studentId  . '_' . $currentDate . '_' .$randomNumber;
        $fullFileName = $fileName . '.' . $extension;
        $publicPath = ROOT_PATH . 'public';
        if ($type == 1){
            $fileTypeName = 'homework_pictures';
        }else if ($type == 2){
            $fileTypeName = 'artical_pictures';
        }else{
            $fileTypeName = 'dayi_pictures';
        }
        $fullUrl = $publicPath . '/storage/'.$fileTypeName.'/' .$fullFileName;
        $savePath = $publicPath.'/storage/'.$fileTypeName.'/';

        $info = $file->move($savePath, $fullFileName);
        if ($info) {
            // 设置文件权限为 755
            if (!chmod($fullUrl, 0755)) {
                // 权限设置失败
                $this->error('文件权限设置失败');
            }
            if ($type == 1){
               
                //  保存作业数据库  t_homework
                $homework = Homework::create([
                    'student_id' => $studentId,
                    'original_image' => '/storage/'.$fileTypeName.'/' .$fullFileName,
                ]);
                //新增任务关联表
                // Db::name("homework_assignment_relation")->insert([
                //     'homework_id' => $homework->id,
                //     'assignment_id' => $assignmentId,
                // ]);
                // 6. 返回结果
                $this->success(
                    '作业提交成功',[
                    'homework_id' => $homework->id,
                    'assignment_id' => $assignmentId,
                    'student_id' =>$studentId,
                    'url'=>'/storage/'.$fileTypeName.'/' .$fullFileName
                ]);
                
            }else{
                $this->success('提交成功',['url'=>'/storage/'.$fileTypeName.'/' .$fullFileName]);
            }

        } else {
            $this->error('上传失败');
        }

    }
    public function callDeepSeekAPI($imagePath)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }

        try {
            // 将图片转换为base64编码
            $imageData = base64_encode(file_get_contents($imagePath));
            // 获取图片MIME类型
            $mimeType = $this->getMimeType($imagePath);
            $apiEndpoint =  'chat/completions';
            // 使用DeepSeek的Chat Completions API来处理图像
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
                "model" => "doubao-1.5-vision-lite-250315",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        'content' => [
                            [
                                'type' => 'image_url',
                                'image_url' => [
                                    'url' => "data:$mimeType;base64,$imageData"
                                ]
                            ],
                            [
                                'type' => 'text',
                                // 'text' => '你是一名专业作业批改AI。请分析图片中的题目：1)判断每道题正误 2)识别所属学科 3)提供简明解析 4)生成检测报告 5)输出严格按此JSON格式：{"list":[{"question":"题目","answer":"答案","correct":"正确/错误","explained":"详解"}],"subject":"主要科目","comment":"整体点评"}。要求：响应快速、解析精准、格式规范。'
                                'text' => '你是一名专业作业批改AI。请分析图片中的题目：1)判断每道题正误 2)识别所属学科 3)提供简明解析 4)生成检测报告 5)输出严格按此JSON格式：{"list":[{"question":"题目","answer":"答案","correct":"正确/错误","explained":"详解"}],"subject":"主要科目","comment":"整体点评","report":{"weak_points":["薄弱知识点1", "薄弱知识点2"], "improvement_suggestions":"改进建议","error_analysis":[{"question_number":"题号", "error_type":"错误类型", "error_reason":"具体归因", "loss_type":"失分类型"}]},"ability_analysis":{"analysis_application":"分析与应用能力评价", "comprehensive_exploration":"综合与探究能力评价", "ability_level":"能力层级总体评估"},"score_summary":{"total_score":"总分","full_score":"满分","score_rate":"得分率","class_level":"班级水平","progress_trend":"进步趋势"}}}。要求：响应快速、解析精准、格式规范。'
                                // 'text' => '请把我获取到图片中的题目,并对这道题进行解答,是否正确,并对每道题进行详解是属于哪个科目的比如数学 语文等,并对这份作业做个点评。json格式返回，例如 { "list":{{"question":"题目1","answer":"答案1","correct":"是否正确","explained":"题目详解"}}, "subject": "科目","comment":"点评"}'
                            ]
                        ]
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseApiHomeWorkResponse($apiResponse);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }
    /**
     * 错题详解
     * @ApiMethod (POST)
     * @ApiParams (name="wrong_id", type="array", required=true, description="错题id")
     * @ApiParams (name="content", type="array", required=true, description="错题内容")
     */
   public function wrongContent()
    {
        $data = input('post.');
        if (empty($data['wrong_id'])) {
            $this->error('缺少错题ID参数');
        }

        $wrongId = $data['wrong_id'];
        $content = Db::name('timu_record')->where('id', $wrongId)->find();
        
        if (empty($content)) {
            $this->success('未找到指定的错题记录', []);
        }

        // 获取错题详解
        $results = $this->wrongDetail($content['question']);

        // 处理detail和analysis的JSON存储
        $updateData = [
            'detail' => json_encode($results['detail'], JSON_UNESCAPED_UNICODE),
            'analysis' => json_encode($results['analysis'], JSON_UNESCAPED_UNICODE),
            'summary' => $results['summary'],
            'knowledge_points' => json_encode($results['knowledge'], JSON_UNESCAPED_UNICODE),
            'update_time' => time()
        ];

        // 更新数据库
        $affected = Db::name('timu_record')
            ->where('id', $wrongId)
            ->update($updateData);

        if ($affected === false) {
            $this->error('更新错题记录失败');
        }

        // 返回格式化后的数据
        $responseData = [
            'question' => $content['question'],
            'detail' => $results['detail'],  // 保持原始数组格式
            'analysis' => $results['analysis'],  // 保持原始数组格式
            'summary' => $results['summary'],
            'knowledge_points' => $results['knowledge']
        ];

        $this->success('获取错题详解成功', $responseData);
    }
    public function wrongDetail($content)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }
        try {

            $apiEndpoint =  'chat/completions';
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
//                "model" => "doubao-1-5-thinking-vision-pro-250428",
                "model" => "deepseek-v3-250324",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        // "content" => '请根据题目' . $content . '写出一条详解、分析、总结，json格式返回，例如 { "detail":"详解","analysis":"分析","summary":"总结" }'
                         "content" => '请根据题目' . $content . '得到详解、分析、总结和这道题目所有知识点以最新版的人教版的目录显示的知识点方式返回，json格式返回，例如  { "detail":"详解","analysis":"分析","summary":"总结","knowledge":["知识点1","知识点2"] }'
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            $rawContent = $apiResponse['choices'][0]['message']['content'];
            if (strpos($rawContent, '```json') !== false) {
                preg_match('/```json\s*([\s\S]+?)\s*```/', $rawContent, $matches);
                return json_decode($matches[1] ?? '{}', true);
            }
            $result = json_decode(stripslashes($rawContent), true);
            return $result;

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }
    /**
     * 提交的作业(图片)请求openai
     * @ApiMethod (POST)
     * @ApiParams (name="homework_id", type="array", required=true, description="作业id集合")
     * @ApiParams (name="assignment_id", type="array", required=true, description="布置作业id")
     * @ApiParams (name="student_id", type="array", required=true, description="学生ID")
     */
    public function homeworkToAiWork() {
        try {
            $param = input();
            
            // 1. 安全获取参数
            $homework_id = (array)($param['homework_id'] ?? []);
            $assignmentId = (int)($param['assignment_id'] ?? 0);
            $student_id = (int)($param['student_id'] ?? 0);
            
            if (empty($homework_id)) {
                return json(['code' => 400, 'msg' => '作业ID不能为空']);
            }
    
            // 2. 删除旧数据（添加类型检查）
            $har = Db::name("homework_assignment_relation")
                ->where(['assignment_id' => $assignmentId])
                ->column('homework_id');
                
            if (!empty($har)) {
                $homeworkIds = Db::name("homework")
                    ->whereIn('id', $har)
                    ->where('student_id', $student_id)
                    ->column('id');
                    
                if (!empty($homeworkIds)) {
                    Db::transaction(function() use ($homeworkIds, $assignmentId, $student_id) {
                        Db::name("homework")->whereIn('id', $homeworkIds)->delete();
                        Db::name("homework_assignment_relation")->whereIn('homework_id', $homeworkIds)->delete();
                        Db::name("homework_corrections")->where([
                            'assignment_id' => $assignmentId,
                            'student_id' => $student_id,
                        ])->delete();
                    });
                }
            }
    
            // 3. 处理新数据
            $combinedResult = [
                'list' => [],
                'knowledge' => '',
                'comment' => '',
                'subject' => '',
                'original_images' => []
            ];
            
            // 批量插入关联关系
            $relationData = array_map(function($id) use ($assignmentId) {
                return [
                    'homework_id' => (int)$id,
                    'assignment_id' => $assignmentId
                ];
            }, $homework_id);
            
            Db::name("homework_assignment_relation")->insertAll($relationData);
    
            // 4. 处理作业内容
            $homeworkList = Db::name("homework")->whereIn('id', $homework_id)->select();
            $studentId = null;
            $assignment_id = 0;
            
            foreach ($homeworkList as $homework) {
                if ($homework['status'] != 0) continue;
                
                $assignment = Db::name("homework_assignment_relation")
                    ->where("homework_id", $homework['id'])
                    ->find();
                if (!$assignment) continue;
                    
                $assignment_id = $assignment['assignment_id'];
                $studentId = $homework['student_id'];
                $currentHomeworkId = $homework['id'];
                $originalImagePath = $homework['original_image'] ?? '';
                
                if (empty($originalImagePath)) continue;
                
                // 5. 调用API处理
                $resource = null;
                for ($retry = 0; $retry < 3; $retry++) {
                    $response = $this->callDeepSeekAPI(ROOT_PATH . 'public' . $originalImagePath);
                    if (!empty($response['resource'])) {
                        $resource = json_decode($response['resource'], true);
                        if (!empty($resource['list'])) break;
                    }
                    sleep(1);
                }
                
                if (!$resource) continue;
                
                // 6. 处理返回数据
                $processedList = array_map(function($item) {
                    return [
                        'question' => $this->convertLatexToDisplay($item['question'] ?? ''),
                        'answer' => $this->convertLatexToDisplay($item['answer'] ?? ''),
                        'explained' => $this->convertLatexToDisplay($item['explained'] ?? ''),
                        'correct' => $item['correct'] ?? ''
                    ];
                }, $resource['list'] ?? []);
                
                $combinedResult['list'] = array_merge($combinedResult['list'], $processedList);
                $combinedResult['knowledge'] .= ($resource['knowledge'] ?? '') . "\n";
                $combinedResult['comment'] .= ($resource['comment'] ?? '') . "\n";
                $combinedResult['subject'] = $combinedResult['subject'] ?: ($resource['subject'] ?? '');
                $combinedResult['original_images'][] = $originalImagePath;
                // $combinedResult['report'] = $resource['report'] ?? '';
                // $combinedResult['ability_analysis'] = $resource['ability_analysis'] ?? '';
                // $combinedResult['score_summary'] = $resource['score_summary'] ?? '';
                // 合并分析数据
                // if (!empty($resource['report'])) {
                //     $combinedResult['report'] = array_merge_recursive(
                //         $combinedResult['report'] ?? [], 
                //         $resource['report']
                //     );
                // }
                
                // if (!empty($resource['ability_analysis'])) {
                //     $combinedResult['ability_analysis'] = array_merge_recursive(
                //         $combinedResult['ability_analysis'] ?? [], 
                //         $resource['ability_analysis']
                //     );
                // }
                
                // if (!empty($resource['score_summary'])) {
                //     $combinedResult['score_summary'] = array_merge_recursive(
                //         $combinedResult['score_summary'] ?? [], 
                //         $resource['score_summary']
                //     );
                // }
                
                // 7. 保存题目记录
                if (!empty($processedList)) {
                    $timuData = array_map(function($item) use ($studentId, $currentHomeworkId, $combinedResult) {
                        return [
                            'student_id' => $studentId,
                            'homework_id' => $currentHomeworkId,
                            'subject' => $combinedResult['subject'],
                            'question' => $item['question'],
                            'correct' => ($item['correct'] == '正确') ? 1 : 2,
                            'answer' => $item['answer'],
                            'create_time' => time()
                        ];
                    }, $processedList);
                    
                    Db::name("timu_record")->insertAll($timuData);
                    Db::name("homework")->where("id", $currentHomeworkId)->update(['status' => 1]);
                }
            }
            
            // 8. 保存批改结果
            if ($studentId && $assignment_id) {
                $dis = ["assignment_id" => $assignment_id, 'student_id' => $studentId];
                $row = Db::name("homework_corrections")->where($dis)->find();
                
                $saveData = [
                    'subject' => $combinedResult['subject'],
                    'original_image' => implode(',', $combinedResult['original_images']),
                    'comment' => trim($combinedResult['comment']),
                    // 'report' => json_encode(  // 新增 report 字段保存
                    //     $combinedResult['report'] ?? [],
                    //     JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
                    // ),
                    // 'ability_analysis' => json_encode(  // 新增 ability_analysis 字段保存
                    //     $combinedResult['ability_analysis'] ?? [],
                    //     JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
                    // ),
                    // 'score_summary' => json_encode(  // 新增 score_summary 字段保存
                    //     $combinedResult['score_summary'] ?? [],
                    //     JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
                    // ),
                    'update_time' => time()
                ];
                
                if ($row) {
                    // 合并历史数据
                    $oldList = json_decode($row['get_ai_content'] ?? '[]', true) ?: [];
                    $saveData['get_ai_content'] = json_encode(
                        array_merge($oldList, $combinedResult['list']),
                        JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
                    );
                    Db::name("homework_corrections")->where($dis)->update($saveData);
                } else {
                    $saveData['get_ai_content'] = json_encode(
                        $combinedResult['list'],
                        JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
                    );
                    $saveData['create_time'] = time();
                    $saveData += $dis;
                    Db::name("homework_corrections")->insert($saveData);
                }
            }
            
            return json([
                'code' => 200,
                'msg' => '批改完成',
                'data' => $combinedResult
            ]);
            
        } catch (\Throwable $e) {
            // 记录完整错误信息
            error_log(sprintf(
                "作业批改失败: %s\nTrace: %s\nInput: %s",
                $e->getMessage(),
                $e->getTraceAsString(),
                json_encode(input(), JSON_UNESCAPED_UNICODE)
            ));
            return json(['code' => 500, 'msg' => '处理失败: ' . $e->getMessage()]);
        }
    }
    
    /**
     * 作业检测报告
     * @ApiMethod (POST)
     * @ApiParams (name="file", type="file", required=true, description="上传的文件")
     * @ApiParams (name="student_id", type="int", required=true, description="学生id")
     */
    public function diagnosticReport()
    {
        $files = $this->request->file('files');
        $studentId = $this->request->post('student_id');
        
        if (!$files) {
            $this->error('请上传图片');
        }
        
        // 确保 $files 是数组（支持多文件上传）
        if (!is_array($files)) {
            $files = [$files];
        }
        
        $results = [];
        $uploadedFiles = [];
        $res = [];
        foreach ($files as $file) {
            $info = $file->getInfo();
            $extension = $this->getExtensionFromMimeType($info['type']);
            
            // 验证文件大小和类型
            $arr_ext = ["jpg", "jpeg", "png", "gif"];
            if (!in_array($extension, $arr_ext)) {
                $this->error('图片格式不支持: ' . $info['name']);
            }
            
            $timestamp = time();
            $currentDate = date('YmdHis', $timestamp);
            $randomNumber = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
            $fileName = $studentId . '_' . $currentDate . '_' . $randomNumber;
            $fullFileName = $fileName . '.' . $extension;
            $publicPath = ROOT_PATH . 'public';
            
            $fullUrl = $publicPath . '/storage/diagnostic_report/' . $fullFileName;
            $savePath = $publicPath . '/storage/diagnostic_report/';
            $info = $file->move($savePath, $fullFileName);
            if ($info) {
                // 设置文件权限为 755
                if (!chmod($fullUrl, 0755)) {
                    $this->error('文件权限设置失败: ' . $fullFileName);
                }
                
                // 调用诊断API
                $result = $this->diagnosticReportAPI($fullUrl);
                $decodedResult = json_decode($result['resource'] ?? '{}', true);
                
                // 对结果进行LaTeX转义
                array_walk_recursive($decodedResult, function(&$value) {
                    if (is_string($value)) {
                        $value = $this->convertLatexToDisplay($value);
                    }
                });
                // 使用 array_merge_recursive 合并每个图片的分析结果
                $results = array_merge_recursive($results, $decodedResult);
                
                $uploadedFiles[] = '/storage/diagnostic_report/' . $fullFileName;
            } else {
                $this->error('文件上传失败: ' . $file->getError());
            }
        }
        
        
        // 保存到数据库（将所有图片的分析结果保存为一条记录）
        DiagnosticReport::create([
            'student_id' => $studentId,
            'original_image' => json_encode($uploadedFiles, JSON_UNESCAPED_UNICODE), // 保存多个文件路径
            'report' => json_encode($results, JSON_UNESCAPED_UNICODE), // 保存合并后的分析结果
        ]);
        
        $this->success('检测报告生成成功', $results);
    }

    // public function diagnosticReport()
    // {
    //     // $param = input();
    //     $files = $this->request->file('files');
    //     $studentId = $this->request->post('student_id');
    //      if (!$files) {
    //         $this->error('请上传图片');
    //     }
        
    //     $info = $files->getInfo();
    //     $extension = $this->getExtensionFromMimeType($info['type']);
    //     // 验证文件大小和类型
    //     $arr_ext = ["jpg","jpeg","png","gif"];
    //     if (!in_array($extension, $arr_ext)){
    //         $this->error('图片格式不支持');
    //     }
    //     $timestamp = time(); // 当前时间戳
    //     $currentDate = date('YmdHis', $timestamp);

    //     $randomNumber = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
    //     $fileName = $studentId  . '_' . $currentDate . '_' .$randomNumber;
    //     $fullFileName = $fileName . '.' . $extension;
    //     $publicPath = ROOT_PATH . 'public';

    //     $fullUrl = $publicPath . '/storage/diagnostic_report'.'/' .$fullFileName;
    //     $savePath = $publicPath.'/storage/diagnostic_report'.'/';
    //     $info = $files->move($savePath, $fullFileName);
    //     if ($info) {
    //         // 设置文件权限为 755
    //         if (!chmod($fullUrl, 0755)) {
    //             // 权限设置失败
    //             $this->error('文件权限设置失败');
    //         }
    //         $result = $this->diagnosticReportAPI(ROOT_PATH . 'public' . '/storage/diagnostic_report' . '/' .$fullFileName);
    //         $decodedResult = json_decode($result['resource'] ?? '{}', true);
    //         array_walk_recursive($decodedResult, function(&$value) {
    //             if (is_string($value)) {
    //                 $value = $this->convertLatexToDisplay($value);
    //             }
    //         });
    //         DiagnosticReport::create([
    //             'student_id' => $studentId,
    //             'original_image' => '/storage/diagnostic_report' . '/' .$fullFileName,
    //             'report' => json_encode(  // 新增 report 字段保存
    //                 $decodedResult ?? [],
    //                 JSON_UNESCAPED_UNICODE
    //             ),
    //         ]);
    //         $this->success('检测报告生成成功', $decodedResult);
            
    //     }
        // $homework_id = (array)($param['homework_id'] ?? []);
        // $assignment_id = (int)($param['assignment_id'] ?? 0);
        // $student_id = (int)($param['student_id'] ?? 0);
        
        // if (empty($homework_id)) {
        //     $this->error('作业ID不能为空');
        // }
        
        // $homeworkList = Db::name("homework")->whereIn('id', $homework_id)->select();
        // if (empty($homeworkList)) {
        //     $this->error('作业ID不存在');
        // }
        // $dis = ["assignment_id" => $assignment_id, 'student_id' => $student_id];
        // $row = Db::name("homework_corrections")->where($dis)->find();
        // $results = [];
        
        
        // if(!$row['report']){
        //     foreach ($homeworkList as $homework) {
        //         $result = $this->diagnosticReportAPI(ROOT_PATH . 'public' . $homework['original_image']);
        //         $decodedResult = json_decode($result['resource'] ?? '{}', true);
                
        //         // 调用 convertLatexToDisplay 进行转义
        //         array_walk_recursive($decodedResult, function(&$value) {
        //             if (is_string($value)) {
        //                 $value = $this->convertLatexToDisplay($value);
        //             }
        //         });
                
        //         $results[] = $decodedResult;
        //     }
        //     $saveData = [
        //         'report' => json_encode(  // 新增 report 字段保存
        //             $results ?? [],
        //             JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
        //         ),
        //     ];
        //     Db::name("homework_corrections")->where($dis)->update($saveData);
        //     $this->success('获取错题详解成功', $results);
        // }
        // $this->success('获取错题详解成功', json_decode($row['report']));
    // }
    public function diagnosticReportAPI($imagePath)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }

        try {
            // 将图片转换为base64编码
            $imageData = base64_encode(file_get_contents($imagePath));
            // 获取图片MIME类型
            $mimeType = $this->getMimeType($imagePath);
            $apiEndpoint =  'chat/completions';
            // 使用DeepSeek的Chat Completions API来处理图像
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
                "model" => "doubao-1.5-vision-lite-250315",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        'content' => [
                            [
                                'type' => 'image_url',
                                'image_url' => [
                                    'url' => "data:$mimeType;base64,$imageData"
                                ]
                            ],
                            [
                                'type' => 'text',
                                'text' => '你是一名专业的教育专家，请对这份作业进行详细分析。请以JSON格式返回分析结果，结构如下：
                                        {
                                            "overall_evaluation": {
                                                "score": "总体评分",
                                                "strengths": ["优势1", "优势2"],
                                                "weaknesses": ["不足1", "不足2"]
                                            },
                                            "error_analysis": [
                                                {
                                                    "question_number": "题号",
                                                    "error_type": "知识性错误/计算错误/理解错误",
                                                    "error_reason": "具体错误原因分析",
                                                    "correct_method": "正确解法",
                                                    "knowledge_points": ["涉及知识点"]
                                                }
                                            ],
                                            "ability_assessment": {
                                                "knowledge_mastery": "知识掌握程度评价",
                                                "thinking_ability": "思维能力评价", 
                                                "comprehensive_application": "综合应用能力评价"
                                            },
                                            "improvement_suggestions": ["具体改进建议1", "具体改进建议2"]
                                        }'
                                // 'text' => '你是一名专业作业批改AI。请分析图片中的作答生成检测报告。json格式返回，例如 {"error_analysis":[{"question_number":"题号", "error_type":"错误类型", "error_reason":"具体归因", "loss_type":"失分类型"}]},"ability_analysis":{"analysis_application":"分析与应用能力评价", "comprehensive_exploration":"综合与探究能力评价", "ability_level":"能力层级总体评估"}}'
                                // 'text' => '请把我获取到图片中的题目,并对这道题进行解答,是否正确,并对每道题进行详解是属于哪个科目的比如数学 语文等,并对这份作业做个点评。json格式返回，例如 { "list":{{"question":"题目1","answer":"答案1","correct":"是否正确","explained":"题目详解"}}, "subject": "科目","comment":"点评"}'
                            ]
                        ]
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseApiHomeWorkResponse($apiResponse);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }
    /**
     * 通过要求写作文
     */
    public function callDeepSeekAPIToEssay($content,$userId)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }
        try {

            $apiEndpoint =  'chat/completions';
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
//                "model" => "doubao-1-5-thinking-vision-pro-250428",
                "model" => "deepseek-v3-250324",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        "content" => '根据下面要求，写一篇英语作文' . $content
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
                'timeout' => Config::get('deepseek.timeout'),
                'verify' => false, 
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseEssayApiResponse($apiResponse,$content,$userId);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }
    
    private function parseEssayApiResponse($apiResponse, $content,$userId)
    {

        $result = $apiResponse['choices'][0]['message']['content'];
        $arr = [
            'answer'=>$result
        ];
        
        //记录到表中wdl_essay
        Essay::create([
            'user_id' => $userId,
            'content' => $content,
            'answer' => $result,
        ]);
        return $arr;
    }

    /**
     * 提交的作业(图片)请求openai
     * @ApiMethod (POST)
     * @ApiParams (name="homework_id", type="array", required=true, description="作业id集合")
     */
    // public function homeworkToAiWork(){
    //     try {
    //         $param = input();
    //         $homework_id = $param['homework_id'];
    //         if (!$homework_id){
    //             return ;
    //         }
    //         $content = '';
    //         $result = '';
    //         $knowledge = '';
    //         $comment = '';
    //         $subject = '';
            
    //         $assignment_id = 0;
    //         $homeworkList = Db::name("homework")->where("id",'in',$homework_id)->select();
    //         if (count($homeworkList) > 0){
    //             foreach ($homeworkList as $homework){
    //                 $assignment= Db::name("homework_assignment_relation")->where("homework_id",$homework['id'])->find();
    //                 $assignment_id = $assignment['assignment_id'];
    //                 if (isset($homework) && $homework['status'] == 0){
    //                     $studentId = $homework['student_id'];
    //                     $homework_id = $homework['id'];
    //                     $originalImagePath = $homework['original_image'];
    //                     //补全url地址
    //                     $publicPath = ROOT_PATH . 'public'.$originalImagePath;
    //                     $response = $this->callDeepSeekAPI($publicPath);
    //                     $resource = $response['resource'];
    //                     if (!empty($resource)) {
    //                         // 解析JSON并转义特殊字符
    //                         $resource = is_array($response['resource']) ? $response['resource'] 
    //                             : json_decode($response['resource'], true);

    //                         $homework['status'] = 1;//ai批改完成
    //                         $list = $resource['list'] ?? '';
    //                         $knowledge = $resource['knowledge'] ?? '';
    //                         $comment .= $resource['comment'] ?? '';
    //                         $subject  = $resource['subject'] ?? '';
                            
    //                         Db::name("homework")->where("id",$homework_id)->update($homework);
    //                         //将每道题输入到记录中
    //                         foreach ($list as $value){
    //                             $timuRecord = TimuRecord::create([
    //                                 'student_id' => $studentId,
    //                                 'homework_id' => $homework_id,
    //                                 'question' => $value['question'],
    //                                 'answer' => $value['answer'],
    //                                 'correct' => $value['correct']=='正确'?1:2,
    //                                 'analysis' => $value['analysis'] ?? null,
    //                                 'detail' => $value['detail'] ?? null,
    //                                 'summary' => $value['summary'] ?? null,
    //                                 'subject' => $subject,
    //                             ]);
                                
    //                             $timuId = $timuRecord->id;
                                
    //                             if($value['correct'] !== '正确'){
    //                                 if (!empty($value['topic']) && is_array($value['topic'])) {
    //                                     foreach ($value['topic'] as $topic) {
    //                                         // 确保topic内容有效
    //                                         if (empty($topic)) {
    //                                             continue;
    //                                         }
                                            
    //                                         $imageSrc = $this->timuImage($topic);
    //                                         $zhishi = Zhishi::create([
    //                                             'content' => $topic,
    //                                             'zhishi_img' => $imageSrc
    //                                         ]);
                                            
    //                                         TimuZhishiRecord::create([
    //                                             'timu_id' => $timuId,
    //                                             'zhishi_id' => $zhishi->id,
    //                                         ]);
                                            
    //                                     }
    //                                 }
    //                             }
    //                         }
    //                     }
    //                 }
    //             }
    //         }
    //         foreach ($list as &$item) {
    //             $item['question'] = $this->convertLatexToDisplay($item['question'] ?? '');
    //             $item['answer'] = $this->convertLatexToDisplay($item['answer'] ?? '');
    //             $item['explained'] = $this->convertLatexToDisplay($item['explained'] ?? '');
    //         }
    //         unset($item); // 解除引用
    //         $jsonData = json_encode($list, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    //         HomeworkCorrections::create([
    //             'student_id' => $studentId,
    //             'assignment_id' => $assignment_id,
    //             'get_ai_content' => $jsonData,
    //             'correction_result' => $result,
    //             'knowledge' => $knowledge,
    //             'comment' => $comment,
    //             'subject' => $subject,
    //             'original_image' => $originalImagePath,
    //         ]);
            
    //         return json(['code' => 200, 'msg' => '批改成功', 'date'=>[
    //             'student_id' => $studentId,
    //             'assignment_id' => $assignment_id,
    //             'get_ai_content' => $jsonData,
    //             'correction_result' => $result,
    //             'knowledge' => $knowledge,
    //             'comment' => $comment,
    //             'subject' => $subject,
    //             'original_image' => $originalImagePath,
    //         ]]);

    //     }catch (\Exception $e){
    //         $this->error( '提交失败：' . $e->getMessage());
    //     }

    // }

    private function convertLatexToDisplay(string $text): string {
        if (empty(trim($text))) {
            return $text;
        }
        // 1. 转换所有frac分数（支持嵌套）
        while (preg_match('/\\$?frac\{([^{}]+)\}\{([^{}]+)\}\\$?/', $text)) {
            $text = preg_replace_callback(
                '/\\$?frac\{([^{}]+)\}\{([^{}]+)\}\\$?/',
                function($matches) {
                    $numerator = $matches[1];
                    $denominator = $matches[2];
                    return (preg_match('/[+\-*\/]/', $numerator) ? "($numerator)" : $numerator) . '/' . 
                        (preg_match('/[+\-*\/]/', $denominator) ? "($denominator)" : $denominator);
                },
                $text
            );
        }
       // 处理cases语法
        $text = preg_replace_callback(
            '/(\\\\)?begin{cases}(.*?)(\\\\)?end{cases}/is',
            function($matches) {
                $content = trim($matches[2]);
                
                // 处理所有可能的分隔符（包括多种空格情况）
                $items = preg_split('/\\\\\\\|\s{2,}|[[:space:]]+/u', $content, -1, PREG_SPLIT_NO_EMPTY);
                
                $formatted = array_map(function($item) {
                    $item = trim($item);
                    // 处理 & 对齐符
                    return str_replace('&', '⇒', $item);
                }, $items);
                
                return "{\n  " . implode("\n  ", $formatted) . "\n}";
            },
            $text
        );

        // 处理特殊符号
        $symbols = [
            'alpha' => 'α', 'beta' => 'β', 'theta' => 'θ', 'pi' => 'π',
            'times' => '×', 'div' => '÷', 'pm' => '±', 'cdot' => '·',
            'geq' => '≥', 'leq' => '≤', 'neq' => '≠', 'eq' => '=',
            'sin' => 'sin', 'cos' => 'cos', 'log' => 'log',
            'Delta' => 'Δ', 'parallel' => '∥', 'angle' => '∠',
            'aeq0' => 'a≠0',
            'circ' => '°'
        ];
        $text = str_replace(array_keys($symbols), array_values($symbols), $text);

        

        // 转换根号（支持高次根）
        $text = preg_replace_callback('/\\$?sqrt(?:\[([0-9]+)\])?\{([^{}]+)\}\\$?/', function($m) {
            $degree = $m[1] ?? null;
            $content = $m[2];
            $rootSymbol = ['3' => '∛', '4' => '∜'];
            return ($degree ? ($rootSymbol[$degree] ?? '√') : '√') . $content;
        }, $text);

        // 处理上标
        $text = preg_replace_callback('/\^\{?([0-9a-zA-Z]+)\}?/', function($m) {
            $map = ['0'=>'⁰', '1'=>'¹', '2'=>'²', '3'=>'³', 'n'=>'ⁿ', 'a'=>'ᵃ','-2'=>'⁻²'];
            return implode('', array_map(fn($c) => $map[$c] ?? $c, str_split($m[1])));
        }, $text);

        // 处理下标
        $text = preg_replace_callback('/_\{?([0-9a-zA-Z]+)\}?/', function($m) {
            $map = ['0'=>'₀', '1'=>'₁', '2'=>'₂', '3'=>'₃', '4' => '₄', '5' => '₅', 'n'=>'ₙ'];
            return implode('', array_map(fn($c) => $map[$c] ?? $c, str_split($m[1])));
        }, $text);
        
        
    // 改进后的指数处理（支持小数和负数）
        $text = preg_replace_callback('/\^\{?([\-0-9.]+)\}?/', function($m) {
            $num = $m[1];
            
            // 处理负号
            $prefix = str_starts_with($num, '-') ? '⁻' : '';
            $num = ltrim($num, '-');
            
            // 数字映射表（扩展更多需要特殊显示的字符）
            $map = [
                '0'=>'⁰', '1'=>'¹', '2'=>'²', '3'=>'³', '4'=>'⁴', '5'=>'⁵',
                '6'=>'⁶', '7'=>'⁷', '8'=>'⁸', '9'=>'⁹', '.' => '·'
            ];
            
            // 转换每个字符
            $result = '';
            foreach (str_split($num) as $char) {
                $result .= $map[$char] ?? $char;
            }
            
            return $prefix . $result;
        }, $text);

         $text = preg_replace_callback(
            '/frac\{(lg|ln|log)(?:\\\\)?\{([^{}]+)\}\}\{(lg|ln|log)(?:\\\\)?\{([^{}]+)\}\}/',
            function($matches) {
                $logType1 = $matches[1];
                $arg1 = $matches[2];
                $logType2 = $matches[3];
                $arg2 = $matches[4];
                
                // 统一使用第一个对数类型
                $logType = $logType1;
                
                // 处理参数中的特殊字符
                $arg1 = str_replace(['\{', '\}'], ['{', '}'], $arg1);
                $arg2 = str_replace(['\{', '\}'], ['{', '}'], $arg2);
                
                return "{$logType}({$arg1})/{$logType}({$arg2})";
            },
            $text
        );
        // 处理对数分数格式（带底数）\frac{log_a{M}}{log_a{N}}
        $text = preg_replace_callback(
            '/frac\{log([a-zA-Z])\{([^{}]+)\}\}\{log\1\{([^{}]+)\}\}/',
            function($matches) {
                $base = $matches[1];    // 底数 a
                $arg1 = $matches[2];    // 真数 M
                $arg2 = $matches[3];    // 真数 N
                return "log{$base}({$arg1})/log{$base}({$arg2})";
            },
            $text
        );
        // 处理带花括号的对数参数（log₅{0.6} → log₅0.6）
        $text = preg_replace_callback(
            '/(log[₀-₉a-zA-Z]+)\{([^{}]+)\}/u',  // 添加/u修饰符处理Unicode下标
            function($matches) {
                // 如果参数是简单数字/字母，移除花括号
                if (preg_match('/^[0-9a-zA-Z.]+$/', $matches[2])) {
                    return $matches[1] . $matches[2];
                }
                return $matches[0]; // 复杂参数保持原样
            },
            $text
        );
        // 处理所有对数函数格式
        $text = preg_replace_callback(
            '/(log|lg|ln)(_([a-zA-Z0-9]+))?\{([^{}]+)\}/',
            function($matches) {
                $func = $matches[1]; // log/lg/ln
                $base = $matches[3] ?? null; // 底数（如果有）
                $arg = $matches[4]; // 参数
                
                // 转换底数为下标
                if ($base) {
                    $base = $this->numberToSubscript($base);
                }
                
                // 判断是否需要保留花括号
                $keepBrace = preg_match('/[+\-*\/^]/', $arg);
                
                return $func . $base . ($keepBrace ? '{'.$arg.'}' : $arg);
            },
            $text
        );
        
        // 处理带转义符的对数表达式lo\\g\\a{M^\\q} = qlo\\g\\a{M} = (logaM)^\\q
        $text = preg_replace_callback(
            '/lo\\\\g\\\\a\{([^{}]+)\^\\\\q\}/',
            function($matches) {
                $argument = $matches[1];
                return '(logₐ'.$argument.')ᑦ'; // 或者使用 q 作为上标
            },
            $text
        );

        // 处理 qlo\g\a{M} 格式
        $text = preg_replace(
            '/qlo\\\\g\\\\a\{([^{}]+)\}/',
            'q·logₐ$1',
            $text
        );

        // 处理 (logaM)^\q 格式
        $text = preg_replace(
            '/\(loga([a-zA-Z])\)\^\\\\q/',
            '(logₐ$1)ᑦ', // 或者使用 q 作为上标
            $text
        );
         $text = preg_replace_callback('/(\d+)\\\\?\/(\d+)/', function($matches) {
            $numerator = $this->numberToSuperscript($matches[1]);
            $denominator = $this->numberToSubscript($matches[2]);
            return "$numerator"."/"."$denominator"; // 使用分数斜线符号

        }, $text);
        
        
        $text = preg_replace([
            '/therefore/',          // 替换 \therefore
            '/because/',
            '/±/',                    // 替换 ± 符号
            '/\(therefore\s+([^)]+)\)/', // 处理完整括号形式
            '/infty/',       // 替换 +infty
        ], [
            '∴',                   // ∴ Unicode符号
            '∵',                   // ∵ Unicode符号
            '±',                    // 保持或替换为+/- 
            '∴ $1',                // 移除外括号
            '∞',                    // ∞ Unicode符号
        ], $text);
        // **underline部分**
        $text = preg_replace_callback('/\\\?underline\s*\{([^{}]*)\}/', function($matches) {
            // return '<u>' . $matches[1] . '</u>'; 
            return "___".$matches[1]."___";
        }, $text);

        // 清除所有$符号
        return str_replace(['\$', '$'], '', $text);
    }

    // 数字转上标
    private function numberToSuperscript(string $num): string {
        $map = ['0'=>'⁰','1'=>'¹','2'=>'²','3'=>'³','4'=>'⁴',
                '5'=>'⁵','6'=>'⁶','7'=>'⁷','8'=>'⁸','9'=>'⁹'];
        return implode('', array_map(fn($c) => $map[$c] ?? $c, str_split($num)));
    }

    // 数字转下标
    private function numberToSubscript(string $num): string {
        $map = ['0'=>'₀','1'=>'₁','2'=>'₂','3'=>'₃','4'=>'₄',
                '5'=>'₅','6'=>'₆','7'=>'₇','8'=>'₈','9'=>'₉'];
        return implode('', array_map(fn($c) => $map[$c] ?? $c, str_split($num)));
    }

    
    
    public function timuImage($topic){
        
        // 设置字体路径（支持 TTF 字体）
        $fontFile = ROOT_PATH . 'public/assets/fonts/simhei.ttf';
        // 检查字体文件是否存在
        if (!file_exists($fontFile)) {
            die("字体文件不存在！");
        }
        
        // 设置图片大小和背景
        $width = 800;
        $height = 100;
        $image = imagecreatetruecolor($width, $height);
        
        // 定义颜色（RGB）
        $backgroundColor = imagecolorallocate($image, 255, 255, 255); // 白色背景
        $textColor = imagecolorallocate($image, 0, 0, 0); // 黑色文字
        
        // 填充背景
        imagefill($image, 0, 0, $backgroundColor);
        
        // 设置字体大小和角度
        $fontSize = 12;
        $angle = 0;
        
        // 计算文字位置（居左对齐）
        $textBox = imagettfbbox($fontSize, $angle, $fontFile, $topic);
        $textWidth = $textBox[2] - $textBox[0];
        $textHeight = $textBox[3] - $textBox[5]; // 修正高度计算
        $x = 10; // 设置左对齐的起始位置，距离左边10像素
        $y = ($height - $textHeight) / 2 + $fontSize;
        
        // 写入文字
        imagettftext($image, $fontSize, $angle, $x, $y, $textColor, $fontFile, $topic);
        $randomNumber = rand();
        
        // 保存图片到 public 文件夹
        $imagePath = ROOT_PATH . 'public/uploads/timu/' .$randomNumber .'.png';
        imagepng($image, $imagePath);
        
        // 释放内存
        imagedestroy($image);
        
        // 返回图片路径
        return  '/uploads/timu/' .$randomNumber .'.png'; // 可以根据需要返回图片的 URL 地址
    }

    /**
     * openai返回的结果进行生成新图片处理
     * @ApiMethod (POST)
     * @ApiParams (name="student_id", type="int", required=true, description="学生id")
     * @ApiParams (name="homework_id", type="int", required=true, description="作业id")
     */
    public function homeworkToAnnotateImage(){
        //todo 此处也是需要异步处理
        $homeworkList = Db::name("homework")->where("status",1)->select();
        if (count($homeworkList) > 0){
            foreach ($homeworkList as $homework){
                $studentId = $homework['student_id'];
                $homework_id = $homework['id'];
                $homework_corrections = Db::name("homework_corrections")->where("homework_id",$homework_id)->find();
                $originalImagePath = $homework['original_image'];
                $correctionResult = $homework_corrections['correction_result'];
                $fullFileName = basename($originalImagePath);
                $publicPath = ROOT_PATH . 'public';
                $originalImagePathlocal = $publicPath . '/storage/homework_pictures/' .$fullFileName;
                // 解析API响应为我们需要的批改结果格式
                $respon = $this->parseApiResponse($correctionResult, $originalImagePathlocal);

                $annotatedImagePath = $this->annotateImage($originalImagePathlocal, $respon);

                if (!empty($annotatedImagePath)) {
                    $homework['status'] = 3;//ai批改完成
                    Db::name("homework")->where("id",$homework_id)->update($homework);
                    HomeworkCorrections::update([
                        'annotated_image' => $annotatedImagePath,
                        'correction_result' => json_encode($respon),
                    ],[
                        'homework_id' => $homework_id,
                        'student_id' => $studentId
                    ]);
                }
            }
        }
    }

    public function test()
    {
        // 1. 验证并获取上传的图片
        $file = $this->request->file('file');
        $studentId = $this->request->post('student_id');
        $homework_id = $this->request->post('homework_id');

        if (!$file) {
            return json(['code' => 400, 'msg' => '请上传作业图片']);
        }
        $info = $file->getInfo();
        $extension = $this->getExtensionFromMimeType($info['type']);
        // 验证文件大小和类型
        $arr_ext = ["jpg","jpeg","png","gif"];
        if (!in_array($extension, $arr_ext)){
            return json(['code' => 400, 'msg' => '图片格式不支持']);
        }

        $timestamp = time(); // 当前时间戳
        $currentDate = date('YmdHis', $timestamp);

        $randomNumber = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
        $fileName = $studentId  . '_' . $currentDate . '_' .$randomNumber;
        $fullFileName = $fileName . '.' . $extension;
        $publicPath = ROOT_PATH . 'public';
        $fullUrl = $publicPath . '/storage/homework_pictures/' .$fullFileName;
        $savePath = $publicPath.'/storage/homework_pictures/';

        $info = $file->move($savePath, $fullFileName);


        $api_url = 'https://api.deepseek.com/v1/ocr';
        $headers = ['Authorization: Bearer YOUR_API_KEY'];
        $data = ['image' => new CURLFile($fullUrl)];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $response = curl_exec($ch);

        print_r($response);exit;

    }
    /**
     * 作业钩叉 此处需要走定时或者mq 异步任务
     *
     * @ApiMethod (POST)
     * @ApiParams (name="account", type="string", required=true, description="账号")
     * @ApiParams (name="password", type="string", required=true, description="密码")
     */
    public function checkHomework()
    {
        try {
            // 1. 验证并获取上传的图片
            $file = $this->request->file('file');
            $studentId = $this->request->post('student_id');
            $homework_id = $this->request->post('homework_id');

            if (!$file) {
                return json(['code' => 400, 'msg' => '请上传作业图片']);
            }
            $info = $file->getInfo();

            $extension = $this->getExtensionFromMimeType($info['type']);


            $timestamp = time(); // 当前时间戳
            $currentDate = date('YmdHis', $timestamp);

            $randomNumber = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
            $fileName = $studentId  . '_' . $currentDate . '_' .$randomNumber;
            $fullFileName = $fileName . '.' . $extension;
            $publicPath = ROOT_PATH . 'public';
            $fullUrl = $publicPath . '/storage/homework_pictures/' .$fullFileName;
            $savePath = $publicPath.'/storage/homework_pictures/';

            $info = $file->move($savePath, $fullFileName);
            if ($info) {
                // 设置文件权限为 755
                if (!chmod($fullUrl, 0755)) {
                    // 权限设置失败
                    return json(['code' => 500, 'msg' => '文件权限设置失败']);
                }

                $originalImagePath = $fullUrl;
                // 3. 调用DeepSeek API进行批改
                $correctionResult = $this->callDeepSeekAPI($originalImagePath,$studentId,$homework_id,$fullFileName);
//                 return json(['code' => 201, 'correctionResult' => $correctionResult]);
                // 4. 在图片上标注批改结果
                $originalImagePathlocal = $publicPath . '/storage/homework_pictures/' .$fullFileName;
                $annotatedImagePath = $this->annotateImage($originalImagePathlocal, $correctionResult);
                
                // 5. 保存批改结果到数据库  t_homework_corrections
                HomeworkCorrections::update([
                    'annotated_image' => str_replace($publicPath, '', $annotatedImagePath),
                ],[
                    'student_id' => $studentId,
                    'homework_id' => $homework_id
                ]);

                // 6. 返回结果
                return json([
                    'code' => 200,
                    'msg' => '作业批改完成',
                    'data' => [
                        'annotated_image_url' => str_replace($publicPath, '', $annotatedImagePath),
                        'correction_result' => $correctionResult
                    ]
                ]);
            } else {
                return json(['code' => 400, 'msg' => '作业上传失败']);
            }

        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '批改失败：' . $e->getMessage()]);
        }
    }


    function getExtensionFromMimeType($mime_type) {
        $mime_to_extension = array(
            'image/jpeg' => array('jpg', 'jpeg'),
            'image/png' => 'png',
            'image/gif' => 'gif',
            'image/bmp' => 'bmp',
            'image/tiff' => 'tiff',
            'image/svg+xml' => 'svg',
            // 添加更多 MIME 类型到扩展名的映射
        );

        if (isset($mime_to_extension[$mime_type])) {
            $extensions = $mime_to_extension[$mime_type];
            if (is_array($extensions)) {
                return  $extensions[0]; // 返回第一个扩展名，如 .jpg
            } else {
                return  $extensions;
            }
        }

        return ''; // 如果没有找到匹配的扩展名，返回空字符串
    }

    public function callDeepSeekAPIToText($content,$userId)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }
        try {

            $apiEndpoint =  'chat/completions';
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');
            // 设置请求体
            $data = [
//                "model" => "doubao-1-5-thinking-vision-pro-250428",
                "model" => "deepseek-v3-250324",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        "content" => $content
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseTextApiResponse($apiResponse,$content,$userId);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }
    }


    /**
     * 调用DeepSeek API进行作业批改
     * @param string $imagePath 图片路径
     * @return array 批改结果
     * @throws \Exception 如果API调用失败
     */
    private function aiDayi($imagePath)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }

        try {
            // 将图片转换为base64编码
            $imageData = base64_encode(file_get_contents($imagePath));
            // 获取图片MIME类型
            $mimeType = $this->getMimeType($imagePath);
            $apiEndpoint =  'chat/completions';
            // 使用DeepSeek的Chat Completions API来处理图像
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');

            // 设置请求体
            $data = [
                "model" => "doubao-1.5-vision-lite-250315",
//                "model" => "deepseek-v3-250324",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        'content' => [
                            [
                                'type' => 'image_url',
                                'image_url' => [
                                    'url' => "data:$mimeType;base64,$imageData"
                                ]
                            ],
                            [
                                'type' => 'text',
                                'text' => '请把我获取到图片中的题目，并对这道题进行解答，是属于哪个科目的比如数学 语文等。json格式返回，例如 { "question":"题目","answer": "答案", "subject": "科目"}'
                            ]
                        ]
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseApiDayiResponse($apiResponse);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }

    }
    /**
     * 调用DeepSeek API进行作业批改
     *
     * @param string $imagePath 图片路径
     * @return array 批改结果
     * @throws \Exception 如果API调用失败
     */
    // public function callDeepSeekAPI($imagePath)
    // {
    //     // 检查API密钥是否已配置
    //     if (empty(Config::get('deepseek.api_key'))) {
    //         throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
    //     }

    //     try {
    //         // 将图片转换为base64编码
    //         $imageData = base64_encode(file_get_contents($imagePath));
    //         // 获取图片MIME类型
    //         $mimeType = $this->getMimeType($imagePath);
    //         $apiEndpoint =  'chat/completions';
    //         // 使用DeepSeek的Chat Completions API来处理图像
    //         // 设置请求的URL
    //         $url = Config::get('deepseek.doubao_url').$apiEndpoint;
    //         // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
    //         $apiKey = Config::get('deepseek.api_key');
    //         // 设置请求体
    //         $data = [
    //             "model" => "doubao-1.5-vision-lite-250315",
    //             "messages" => [
    //                 [
    //                     "role" => "system",
    //                     "content" => "You are a helpful assistant."
    //                 ],
    //                 [
    //                     "role" => "user",
    //                     'content' => [
    //                         [
    //                             'type' => 'image_url',
    //                             'image_url' => [
    //                                 'url' => "data:$mimeType;base64,$imageData"
    //                             ]
    //                         ],
    //                         [
    //                             'type' => 'text',
    //                             'text' => '请把我获取到图片中的题目，把没大题的每小题进行解答并把大题的题目去掉，是否正确如果正确返回正确错误返回错误,并对每道题进行详解如果是理科要列出公式或竖式,我要对每道错题进行错题分析、错题详解、错题总结不少于200字,还要得到错题的知识点标题,根据错题的知识点布置三道文字练习题,
    //                             是属于哪个科目的比如数学 语文等,提取出图片中的他们涉及到的知识点标题,并最后对这份作业做个点评。json格式返回，例如 { "list":{{"question":"题目1",""answer}:"答案1","correct":"是否正确","explained":"题目详解","analysis":"错题分析","detail":"错题详情","summary":"错题总结","wrong_knowledge":"错题知识点标题","topic":["练习题1","练习题2","练习题3"]},{"question":"题目2",""answer}:"答案2","correct":"是否正确","explained":"题目详解","analysis":"错题分析","detail":"错题详情","summary":"错题总结","wrong_knowledge":"错题知识点标题","topic":["练习题1","练习题2","练习题3"]}}, "subject": "科目","knowledge":"知识点标题","comment":"点评"}'
    //                         ]

    //                         // [
    //                         //     'type' => 'text',
    //                         //     'text' => '请把我获取到图片中的题目，并对这道题进行解答，是否正确
    //                         //     是属于哪个科目的比如数学 语文等,并最后对这份作业做个点评。json格式返回，例如 { "list":{{"question":"题目1",""answer}:"答案1","correct":"是否正确"},{"question":"题目2",""answer}:"答案2","correct":"是否正确"}}, "subject": "科目","comment":"点评"}'
    //                         // ]
    //                     ]
    //                 ]
    //             ]
    //         ];

    //         // 发送请求
    //         $client = new Client([
    //             'base_uri' => $url,
    //         ]);


    //         // 发送 POST 请求
    //         $response = $client->post($url, [
    //             'headers' => [
    //                 'Authorization' => 'Bearer ' . $apiKey,
    //                 'Content-Type' => 'application/json'
    //             ],
    //             'json' => $data
    //         ]);
    //         $apiResponse = json_decode($response->getBody()->getContents(), true);
    //         // 解析API响应为我们需要的批改结果格式
    //         return $this->parseApiHomeWorkResponse($apiResponse);

    //     } catch (\GuzzleHttp\Exception\RequestException $e) {
    //         // 处理请求异常
    //         $errorMessage = $e->hasResponse() ?
    //             $e->getResponse()->getBody()->getContents() :
    //             $e->getMessage();

    //         $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
    //         \think\Log::record($msg);

    //         throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

    //     } catch (\Exception $e) {
    //         // 处理其他异常
    //         $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
    //         \think\Log::record($msg);

    //         throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
    //     }
    // }

    /**
     * 获取文件的MIME类型
     *
     * @param string $filePath 文件路径
     * @return string MIME类型
     */
    protected function getMimeType($filePath)
    {
        if (function_exists('mime_content_type')) {
            return mime_content_type($filePath);
        }

        // 如果mime_content_type函数不可用，使用简单的扩展名判断
        $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        $mimeTypes = [
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            // 可以根据需要添加更多类型
        ];

        return $mimeTypes[$ext] ?? 'application/octet-stream';
    }

    /**
     * 解析DeepSeek API响应为批改结果格式
     *
     * @param array $apiResponse API响应
     * @param string $imagePath 图片路径
     * @return array 批改结果
     */
    protected function parseApiResponse($apiResponse, $imagePath)
    {
        try {
            // 获取AI的回复内容
            $content = $apiResponse;
           if (empty($content)) {
                throw new \Exception('API返回的内容为空');
            }

            // 使用正则表达式提取错误位置和描述
            // 这里假设AI返回的内容中包含类似 "错误1：坐标(100,200) - 计算错误" 的格式
            $annotations = [];
            $summary = '';
            // 获取图片尺寸，用于计算相对坐标
//            $imageInfo = getimagesize($imagePath);
            list($imageWidth, $imageHeight) = getimagesize($imagePath);
//            $imageWidth = $imageInfo[0];
//            $imageHeight = $imageInfo[1];
            $content = str_replace('\n', '', $content);
            $content = str_replace('\"', '"', $content);



            // 解析AI返回的内容
            // 这里使用一个简单的方法来提取可能的错误位置
            // 实际应用中，你可能需要根据DeepSeek API的实际返回格式调整这部分代码
            // 先尝试使用JSON格式解析（如果AI返回了结构化数据）
            if (strpos($content, '{') !== false && strpos($content, '}') !== false) {
//                preg_match_all('/\{.*?\}/s', $content, $jsonMatches);
                preg_match('/```(.*?)```/s', $content, $matches);
//                $input = $this->removeEscapeChars($matches[1]);
                $input = $matches[1];
                $pos = strpos($input, 'json');
                // 如果找到了 "json"，则去除它
                if ($pos !== false) {
                    // 从 "json" 之后的位置开始提取内容
                    $jsonContent = substr($input, strlen('json'));
                } else {
                    // 如果没有找到 "json"，则直接使用原始内容
                    $jsonContent = $input;
                }
                // 去除开头和结尾的空白字符
                $jsonContent = trim($jsonContent);
                // 使用正则表达式移除多余的逗号
//                $jsonContent = preg_replace('/,(?=\s*})/', '', $jsonContent);
                // 将 JSON 字符串转换为 PHP 数组

//                print_r($jsonContent);exit;
                $data = json_decode($jsonContent, true);
//                print_r($data );exit;
                $summary = isset($data[ 'summary'])?$data['summary']:'';
                //构造一个最新的数组 包括正确和错误的 每道题的坐标以及是否正确
                $annotations = [];
                if (isset($data['results'])){
                    foreach ($data['results'] as $item) {
                        try {
                            foreach ($item['sub_results'] as $item1){
                                if (isset($item1['answer_coords'])){
                                    $arr = [
                                        'x' => $item1['answer_coords'][0],
                                        'y' => $item1['answer_coords'][1],
                                        'flag' => $item1['correct']?true:false,
                                        'comment' => $item1['comment']
                                    ];
                                    $annotations[] = $arr;
                                }
                            }
                        } catch (\Exception $e) {
                            continue;
                        }
                    }
                }else if (isset($data['list'])){

                    foreach ($data['list'] as $item2) {
                        try {
                            if (isset($item2['coordinates'])){
                                $arr = [
                                    'x' => $item2['coordinates'][0],
                                    'y' => $item2['coordinates'][1],
                                    'flag' => $item2['correct']?true:false,
                                    'comment' => $item2['comment']
                                ];
                            }else if (isset($item2['bbox_2d'])){
                                $arr = [
                                    'x' => $item2['bbox_2d'][2] ,
                                    'y' => $item2['bbox_2d'][3] ,
                                    'flag' => $item2['correct']?true:false,
                                    'comment' => $item2['comment']
                                ];
                            }else{
                                $arr = [
                                    'x' => $item2['x'],
                                    'y' => $item2['y'],
                                    'flag' => $item2['correct']?true:false,
//                                    'flag' => true,
                                    'comment' => $item2['comment']
                                ];
                            }

                            $annotations[] = $arr;

                        } catch (\Exception $e) {
                            continue;
                        }
                    }
//                    print_r($annotations);exit;
                }else if(isset($data)){
                    foreach ($data as $item) {
                        try {
                            if (isset($item['answer_position'])){
                                $arr = [
                                    'x' => $item['answer_position'][0],
                                    'y' => $item['answer_position'][1],
                                    'flag' => $item['correct']?true:false,
                                    'comment' => $item['comment']
                                ];
                                $annotations[] = $arr;
                            }
                            if (isset($item['coordinate'])){
                                $arr = [
                                    'x' => $item['coordinate'][0],
                                    'y' => $item['coordinate'][1],
                                    'flag' => $item['correct']?true:false,
                                    'comment' => $item['comment']
                                ];

                                $annotations[] = $arr;
                            }
                            if (isset($item['坐标'])){
                                // 去掉括号
                                $trimmedStr = substr($item['坐标'], 1, -1);
                                $numbers = explode(",", $trimmedStr);

                                $arr = [
                                    'x' => $numbers[0],
                                    'y' => $numbers[1],
                                    'flag' => $item['correct']?true:false,
                                    'comment' => $item['comment']
                                ];
                                $annotations[] = $arr;
                            }

                        } catch (\Exception $e) {
                            continue;
                        }
                    }
                }
            }

            // 返回最终的批改结果
            return [
                'resource' => $content,
                'annotations' => $annotations,
                'summary' => $summary,
                'image_info' => [
                    'width' => $imageWidth,
                    'height' => $imageHeight
                ]
            ];

        } catch (\Exception $e) {
            // 返回一个默认的批改结果
            return [
                'resource' => $content,
                'annotations' => [],
                'summary' => '无法解析批改结果，请查看原始响应',
                'original_response' => $apiResponse
            ];
        }
    }


    /**
     * 解析DeepSeek API响应为批改结果格式
     *
     * @param array $apiResponse API响应
     * @param string $imagePath 图片路径
     * @return array 批改结果
     */
    protected function parseApiDayiResponse($apiResponse)
    {
        try {
            // 获取AI的回复内容
            $content = $apiResponse['choices'][0]['message']['content'];
            if (empty($content)) {
                throw new \Exception('API返回的内容为空');
            }
            $content = str_replace('\n', '', $content);
            $content = str_replace('\"', '"', $content);
            $data = [];
            // 解析AI返回的内容
            // 先尝试使用JSON格式解析（如果AI返回了结构化数据）
            if (strpos($content, '{') !== false && strpos($content, '}') !== false) {
                preg_match('/```(.*?)```/s', $content, $matches);
                $input = $this->removeEscapeChars($matches[1]);
                $pos = strpos($input, 'json');
                // 如果找到了 "json"，则去除它
                if ($pos !== false) {
                    // 从 "json" 之后的位置开始提取内容
                    $jsonContent = substr($input, strlen('json'));
                } else {
                    // 如果没有找到 "json"，则直接使用原始内容
                    $jsonContent = $input;
                }
                // 去除开头和结尾的空白字符
                $jsonContent = trim($jsonContent);
                return [
                    'resource' => $jsonContent,
                    'summary' => '解析成功',
                    'original_response' => $apiResponse
                ];
            }else{
                return [];
            }
        } catch (\Exception $e) {
            // 返回一个默认的批改结果
            return [
                'resource' => $content,
                'summary' => '无法解析批改结果，请查看原始响应',
                'original_response' => $apiResponse
            ];
        }
    }

    function removeEscapeChars($string) {
        // 定义要移除的转义符
        $escapeChars = [
            '\\' => '',  // 反斜杠
            "\n" => '',  // 换行符
            "\r" => '',  // 回车符
            "\t" => '',  // 制表符
            "\0" => '',  // NULL 字符
            "\x0B" => '' // 垂直制表符
        ];

        // 使用 strtr 函数替换转义符
        return strtr($string, $escapeChars);
    }
    /**
     * 在图片上标注批改结果
     *
     * @param string $imagePath 原始图片路径
     * @param array $correctionResult 批改结果
     * @return string 标注后的图片路径
     */
    protected function annotateImage($imagePath, $correctionResult)
    {
        try {
            // 检查图片是否存在
             if (!file_exists($imagePath)) {
                 throw new \Exception('原始图片不存在：' . $imagePath);
             }

             $imagick = new \Imagick($imagePath);
             if (isset($correctionResult['annotations']) && !empty($correctionResult['annotations'])){
                 foreach ($correctionResult['annotations'] as $annotation) {
                     $draw = new \ImagickDraw();
                     // 确保位置数据存在
                     if ( !isset($annotation['x']) || !isset($annotation['y'])) {
                         $msg = '标注缺少位置信息，跳过，annotation:'.$annotation;
                         \think\Log::record($msg);
                         continue;
                     }

                     $x = (int)$annotation['x'];
                     $y = (int)$annotation['y'];

                     $isCorrect = $annotation['flag'];

                     $draw->setStrokeWidth(100);

                     $draw->setFillColor(new \ImagickPixel('red'));
                     $draw->point($x, $y);
                     if ($isCorrect) {
                         // 绘制对勾
                         $draw->setFillColor(new \ImagickPixel('rgba(0, 255, 0, 0.8)')); // 设置水印颜色和透明度
                         $draw->setFontSize(24); // 设置字体大小
                         $draw->line($x - 30 / 2, $y, $x - 30 / 6, $y + 30 / 3);
                         $draw->line($x - 30 / 6, $y + 30 / 3, $x + 30 / 2, $y - 30 / 3);

                     } else {
                         // 绘制叉号
                         $draw->setFillColor(new \ImagickPixel('rgba(255, 0, 0, 0.8)')); // 设置水印颜色和透明度
                         $draw->setFontSize(24); // 设置字体大小
                         $draw->line($x - 30 / 2, $y - 30 / 2, $x + 30 / 2, $y + 30 / 2);
                         $draw->line($x - 30 / 2, $y + 30 / 2, $x + 30 / 2, $y - 30 / 2);
                     }

                     // 添加水印到图片
                     $imagick->drawImage($draw);
                 }
                 $markedPath = str_replace('.', '_marked.', $imagePath);
                 $imagick->writeImage($markedPath);

                 return $markedPath;
             }else{
                 return '';
             }

        } catch (\Exception $e) {
            $msg = '图片标注失败，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('图片标注失败：' . $e->getMessage());
        }
    }


    protected function drawCheckMark($imagick,$draw, $x, $y, $config)
    {
        $draw->setFillColor(new \ImagickPixel('rgba(255, 255, 255, 0.5)')); // 设置水印颜色和透明度
        $draw->setFontSize(24); // 设置字体大小
//        $draw->setGravity(\Imagick::GRAVITY_SOUTHEAST); // 设置水印位置
        // 绘制对勾
        $draw->line($x - $config['size'] / 2, $y, $x - $config['size'] / 6, $y + $config['size'] / 3);
        $draw->line($x - $config['size'] / 6, $y + $config['size'] / 3, $x + $config['size'] / 2, $y - $config['size'] / 3);
        // 添加水印文本
        $imagick->annotateImage($draw, $x, $y, 0, $config['text']);
        return $imagick;
    }


    protected function drawCrossMark($imagick,$draw, $x, $y, $config)
    {
        $draw->setFillColor(new \ImagickPixel('rgba(199, 199, 199, 0.3)')); // 设置水印颜色和透明度
        $draw->setFontSize(20); // 设置字体大小
//        $draw->setGravity(\Imagick::GRAVITY_WEST); // 设置水印位置
        // 绘制叉号
        $draw->line($x - $config['size'] / 2, $y - $config['size'] / 2, $x + $config['size'] / 2, $y + $config['size'] / 2);
        $draw->line($x - $config['size'] / 2, $y + $config['size'] / 2, $x + $config['size'] / 2, $y - $config['size'] / 2);
        // 添加水印文本
        $imagick->annotateImage($draw, $x, $y, 0, $config['text']);

        return $imagick;
    }

    /**
     * 图片标注配置
     */
    protected $annotationConfig = [
        'correct_mark' => [
            'color' => 'rgba(255, 0, 0, 0.8)',
            'text' => 'red',
            'size' => 30
        ],
        'wrong_mark' => [
            'color' => 'rgba(255, 255, 0, 0.8)',
            'text' => 'yellow',
            'size' => 30
        ]
    ];

    private function createHomeworkCorrection($studentId,$homework_id,$fullFileName,$correctionResult)
    {
        HomeworkCorrections::create([
            'student_id' => $studentId,
            'homework_id' => $homework_id,
            'original_image' => '/storage/homework_pictures/' .$fullFileName,
            'get_ai_content' => json_encode($correctionResult),
        ]);
    }

    private function parseTextApiResponse($apiResponse, $content,$userId)
    {

        $result = $apiResponse['choices'][0]['message']['content'];
        $arr = [
            'answer'=>$result
        ];

        //记录到表中wdl_talk_record
        TalkRecord::create([
            'user_id' => $userId,
            'content' => $content,
            'answer' => $result,
        ]);
        return $arr;
    }


    /**
     * 调用DeepSeek API进行作文批改
     * @param string $imagePath 图片路径
     * @return array 批改结果
     * @throws \Exception 如果API调用失败
     */
    private function aiArtical($imagePath)
    {
        // 检查API密钥是否已配置
        if (empty(Config::get('deepseek.api_key'))) {
            throw new \Exception('DeepSeek API密钥未配置，请在.env文件中设置DEEPSEEK_API_KEY');
        }

        try {
            // 将图片转换为base64编码
            $imageData = base64_encode(file_get_contents($imagePath));
            // 获取图片MIME类型
            $mimeType = $this->getMimeType($imagePath);

            $apiEndpoint =  'chat/completions';
            // 使用DeepSeek的Chat Completions API来处理图像
            // 设置请求的URL
            $url = Config::get('deepseek.doubao_url').$apiEndpoint;
            // 若没有配置环境变量，请用百炼API Key将下行替换为：$apiKey = "sk-xxx";
            $apiKey = Config::get('deepseek.api_key');

            // 设置请求体
            $data = [
                "model" => "doubao-1.5-vision-lite-250315",
                "messages" => [
                    [
                        "role" => "system",
                        "content" => "You are a helpful assistant."
                    ],
                    [
                        "role" => "user",
                        'content' => [
                            [
                                'type' => 'image_url',
                                'image_url' => [
                                    'url' => "data:$mimeType;base64,$imageData"
                                ]
                            ],
                            [
                                'type' => 'text',
                                'text' => '获取到图片中这篇文章的所有的内容，文章内容如果出现有单引号或者双引号等符号帮我处理一下
                                并对这篇文章进行点评，要求如果有错别字或者病句需要改进，请给出改进意见，得到作文使用的修辞手法以及其亮点不得少于两百字，并提出修改意见，并且告诉我是属于哪个科目的比如英语 语文等。
                                json格式返回，例如 { "content":"作文内容","answer": "文章点评","blips":"亮点","advice":"修改意见" ,"subject": "科目"}'
                            ],
                            // [
                            //     'type' => 'text',
                            //     'text' => '获取到图片中这篇文章的所有的内容，文章内容如果出现有单引号或者双引号等符号帮我处理一下
                            //     并对这篇文章进行点评，要求如果有错别字或者病句需要改进，请给出改进意见，并且告诉我是属于哪个科目的比如英语 语文等。
                            //     json格式返回，例如 { "content":"作文内容","answer": "文章点评", "subject": "科目"}'
                            // ]
                        ]
                    ]
                ]
            ];

            // 发送请求
            $client = new Client([
                'base_uri' => $url,
            ]);


            // 发送 POST 请求
            $response = $client->post($url, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json'
                ],
                'json' => $data
            ]);
            $apiResponse = json_decode($response->getBody()->getContents(), true);
            // 解析API响应为我们需要的批改结果格式
            return $this->parseApiArticalResponse($apiResponse);

        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // 处理请求异常
            $errorMessage = $e->hasResponse() ?
                $e->getResponse()->getBody()->getContents() :
                $e->getMessage();

            $msg = 'DeepSeek API调用失败，error:'.$errorMessage.',code:'.$e->getCode();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $errorMessage);

        } catch (\Exception $e) {
            // 处理其他异常
            $msg = 'DeepSeek API调用发生未知错误，error:'.$e->getMessage().',trace:'.$e->getTraceAsString();
            \think\Log::record($msg);

            throw new \Exception('DeepSeek API调用失败：' . $e->getMessage());
        }

    }

    private function parseApiArticalResponse($apiResponse)
    {
        try {
            // 获取AI的回复内容
            $content = $apiResponse['choices'][0]['message']['content'];
            if (empty($content)) {
                throw new \Exception('API返回的内容为空');
            }
            $content = str_replace('\n', '', $content);
            $content = str_replace('\"', '"', $content);

            // 解析AI返回的内容
            // 先尝试使用JSON格式解析（如果AI返回了结构化数据）
            if (strpos($content, '{') !== false && strpos($content, '}') !== false) {
                $content = $this->removeEscapeChars($content);
                // 去除开头和结尾的空白字符
                $jsonContent = trim($content);
                $jsonContent = json_decode($jsonContent, true);
                return [
                    'resource' => $jsonContent,
                    'summary' => '解析成功',
                    'original_response' => $apiResponse
                ];
            }else{
                return [];
            }
        } catch (\Exception $e) {
            // 返回一个默认的批改结果
            return [
                'resource' => $content,
                'summary' => '无法解析批改结果，请查看原始响应',
                'original_response' => $apiResponse
            ];
        }
    }

    private function parseApiHomeWorkResponse($apiResponse)
    {
        try {
            // 获取AI的回复内容
            $content = $apiResponse['choices'][0]['message']['content'];
            if (empty($content)) {
                throw new \Exception('API返回的内容为空');
            }
            $content = str_replace('\n', '', $content);
            $content = str_replace('\"', '"', $content);

            // 解析AI返回的内容
            // 先尝试使用JSON格式解析（如果AI返回了结构化数据）
            if (strpos($content, '{') !== false && strpos($content, '}') !== false) {

                $content = $this->removeEscapeChars($content);
                // 去除开头和结尾的空白字符
                $jsonContent = trim($content);
                return [
                    'resource' => $jsonContent,
                    'summary' => '解析成功',
                    'original_response' => $apiResponse
                ];
            }else{
                return $content;
            }
        } catch (\Exception $e) {
            // 返回一个默认的批改结果
            return [
                'resource' => $content,
                'summary' => '无法解析批改结果，请查看原始响应',
                'original_response' => $apiResponse
            ];
        }
    }
}
